package com.project.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.project.config.Upload;
import com.project.entity.po.*;
import com.project.entity.qo.CommentQo;
import com.project.entity.vo.MemberVo;
import com.project.entity.vo.RechargeRecordVo;
import com.project.entity.vo.UserVo;
import com.project.entity.vo.Vip;
import com.project.exception.ControllerException;
import com.project.exception.ServiceException;
import com.project.mapper.*;
import com.project.entity.qo.MemberQo;
import com.project.entity.qo.UserQo;
import com.project.result.ResponseResult;
import com.project.result.ResultCode;
import com.project.service.UserService;
import com.project.utils.ShiroUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.io.Serializable;
import java.time.Duration;

/**
 * @ProjectName:
 * @Package:
 * @ClassName:
 * @Author: ZhaoLongShi
 * @CreateDate:
 */
@SuppressWarnings("all")
@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private Upload upload;

    @Resource
    private MemberMapper memberMapper;

    @Resource
    private RechargeRecordMapper rechargeRecordMapper;

    @Resource
    private ValueOperations<String, Object> valueOperations;

    @Resource
    private CommentMapper commentMapper;

    /**
     * 根据用户名查询用户是否存在
     *
     * @param username
     * @return
     */
    @Override
    public ResponseResult<UserVo> selectByUsername(String username) {
        User user = userMapper.selectUserByName(username);
        Session session = ShiroUtils.getSession();
        session.setAttribute("user", user);

        UserVo userVo = new UserVo();
        BeanUtils.copyProperties(user, userVo);
        return ResponseResult.success(ResultCode.SUCCESS, userVo);
    }

    /**
     * 根据手机号查询用户是否存在
     *
     * @param phone
     * @return
     */
    @Override
    public ResponseResult<UserVo> selectByPhone(Long phone) {
        //查询用户名是否存在
        User user = userMapper.selectUserByPhone(phone);
        Session session = ShiroUtils.getSession();
        session.setAttribute("user", user);
        UserVo userVo = new UserVo();
        BeanUtils.copyProperties(user, userVo);
        return ResponseResult.success(ResultCode.SUCCESS, userVo);
    }

    /**
     * 注册
     *
     * @param userQo
     * @return
     */
    @Override
    public ResponseResult<ResultCode> register(UserQo userQo) {
        userQo.setRegisterTime(new Date());
        User user = new User();
        User user1 = userMapper.checkNameAndPhone(user.getUsername(), user.getPhone());
        if (ObjectUtils.isEmpty(user1)) {
            BeanUtils.copyProperties(userQo, user);
            int count = userMapper.insert(user);
            if (count == 0) {
                throw new ServiceException(ResultCode.REGISTER_ERROR);
            } else {
                return ResponseResult.success(ResultCode.SUCCESS);
            }
        } else {
            throw new ServiceException(ResultCode.ACCOUNT_IS_EXISTENT);
        }

    }

    /**
     * 更新用户
     *
     * @param userQo
     * @return
     */
    @Override
    public ResponseResult<ResultCode> updateUserById(UserQo userQo) {
        User user = new User();
        BeanUtils.copyProperties(userQo, user);
        int count = userMapper.updateById(user);
        if (count == 0) {
            throw new ServiceException(ResultCode.UPDATE_ERROR);
        } else {
            return ResponseResult.success(ResultCode.SUCCESS);
        }
    }

    /**
     * 修改密码
     *
     * @param oldPassword
     * @param newPassword
     * @return
     */
    @Override
    public ResponseResult<ResultCode> updatePasswordById(String oldPassword,
                                                         String newPassword) {
        Session session = ShiroUtils.getSession();
        User user1 = (User) session.getAttribute("user");
        String sha2561 = ShiroUtils.sha256(oldPassword,null);
        //检查原密码
        User user = userMapper.checkPassword(user1.getUserId(), sha2561);
        if (ObjectUtils.isEmpty(user)) {
            throw new ServiceException(ResultCode.PASSWORD_ERROR);
        } else {
            String sha256 = ShiroUtils.sha256(newPassword, null);
            user.setPassword(sha256);
            int count = userMapper.updateById(user);
            if (count != 1) {
                throw new ServiceException(ResultCode.PASSWORD_ERROR);
            }
            return ResponseResult.success(ResultCode.SUCCESS);
        }
    }

    /**
     * 注册会员
     *
     * @param memberQo
     * @return
     */
    @Override
    public ResponseResult<ResultCode> registerVip(MemberQo memberQo) {
        User user = (User) ShiroUtils.getSessionAttribute("user");
        Long count = userMapper.isVip(user.getUserId());
        if (count == 1) {
            throw new ServiceException(ResultCode.IS_VIP);
        }
        //根据充值余额决定会员类型
        if (memberQo.getBalance() > Vip.VIP_YELLOW_GOLD) {
            memberQo.setCardType(3);
        } else if (memberQo.getBalance() >= Vip.VIP_GRAY_GOLD) {
            memberQo.setCardType(2);
        } else if (memberQo.getBalance() >= Vip.VIP_WHITE_GOLD) {
            memberQo.setCardType(1);
        } else {
            throw new ServiceException(ResultCode.BALANCE_NOT_ENOUGH);
        }
        memberQo.setUsername(user.getUsername());
        memberQo.setUserId(user.getUserId());
        memberQo.setPhone(user.getPhone());
        Member member = new Member();
        BeanUtils.copyProperties(memberQo, member);
        memberMapper.insert(member);
        //注册成为会员后，修改会员状态
        user.setVip(Vip.VIP);
        userMapper.updateById(user);
        return ResponseResult.success(ResultCode.SUCCESS);
    }

    /**
     * 查询会员信息
     *
     * @return
     */
    @Override
    public ResponseResult<MemberVo> selectMemberInfoByUserId() {
        User user = (User) ShiroUtils.getSessionAttribute("user");
        Member member = memberMapper.selectById(user.getUserId());
        MemberVo memberVo = new MemberVo();
        BeanUtils.copyProperties(member, memberVo);
        return ResponseResult.success(memberVo);
    }

    /**
     * 第三方充值到会员
     *
     * @param price
     * @param rechargeType
     * @return
     */
    @Override
    public ResponseResult<ResultCode> rechargeWithOthor(double price, String rechargeType) {
        User user = (User) ShiroUtils.getSessionAttribute("user");
        Member member = memberMapper.selectMemberByUserId(user.getUserId());
        member.setBalance(member.getBalance() + price);
        int i = memberMapper.updateById(member);
        if (i != 1) {
            throw new ServiceException(ResultCode.ERROR);
        }
        //添加充值记录
        RechargeRecord record = new RechargeRecord();
        record.setUserId(user.getUserId());
        record.setUserName(user.getUsername());
        record.setRechargeType(rechargeType);
        record.setRechargeMoney(price);
        record.setRechargeTime(new Date());
        rechargeRecordMapper.insert(record);
        return ResponseResult.success(ResultCode.SUCCESS);
    }

    /**
     * 余额充值到会员
     *
     * @param price
     * @return
     */
    @Override
    public ResponseResult<ResultCode> rechargeWithBalance(double price) {
        User user = (User) ShiroUtils.getSessionAttribute("user");
        //判断余额是否充足
        if (user.getBalance() < price) {
            throw new ServiceException(ResultCode.BALANCE_NOT_ENOUGH);
        }
        Member member = memberMapper.selectMemberByUserId(user.getUserId());
        //成功会员账号加price
        member.setBalance(member.getBalance() + price);
        //余额减price
        user.setBalance(user.getBalance() - price);
        userMapper.updateById(user);
        int i = memberMapper.updateById(member);
        if (i != 1) {
            throw new ServiceException(ResultCode.ERROR);
        }
        RechargeRecord record = new RechargeRecord();
        record.setUserId(user.getUserId());
        record.setUserName(user.getUsername());
        record.setRechargeType(Vip.RECHARGE_TYPE);
        record.setRechargeMoney(price);
        record.setRechargeTime(new Date());
        rechargeRecordMapper.insert(record);
        return ResponseResult.success(ResultCode.SUCCESS);
    }

    /**
     * 充值到余额
     *
     * @param price
     * @return
     */
    @Override
    public ResponseResult<ResultCode> rechargeToBalance(double price) {
        User user = (User) ShiroUtils.getSessionAttribute("user");
        int count = userMapper.rechargeToBalance(user.getUserId(), price);
        if (count != 1) {
            throw new ServiceException(ResultCode.ERROR);
        }
        return ResponseResult.success(ResultCode.SUCCESS);
    }

    /**
     * 查询充值记录
     *
     * @return
     */
    @Override
    public ResponseResult<List<RechargeRecordVo>> selectRecordByUserId() {
        User user = (User) ShiroUtils.getSessionAttribute("user");
        List<RechargeRecord> list = rechargeRecordMapper.selectRecordByUserId(user.getUserId());
        if (ObjectUtils.isEmpty(list)) {
            throw new ServiceException(ResultCode.NO_RECHARGE_RECORD);
        }
        ArrayList<RechargeRecordVo> lists = new ArrayList<>();
        list.forEach(rechargeRecord -> {
            RechargeRecordVo rechargeRecordVo = new RechargeRecordVo();
            BeanUtils.copyProperties(rechargeRecord, rechargeRecordVo);
            lists.add(rechargeRecordVo);
        });
        return ResponseResult.success(ResultCode.SUCCESS, lists);
    }

    /**
     * 查询用户(分页)
     * * @param current
     *
     * @return
     */
    @Override
    public ResponseResult seleteAllUser(int current) {
        Page<User> list = userMapper.selectAllUser(current);
        if (ObjectUtils.isEmpty(list)) {
            throw new ServiceException(ResultCode.ERROR);
        }
        return ResponseResult.success(ResultCode.SUCCESS, list);
    }

    /**
     * 上传文件
     *
     * @param file
     * @return
     */
    @Override
    public String upload(MultipartFile file) {
        String url = upload.uploadImg(file);
        if (ObjectUtils.isEmpty(url)) {
            throw new ServiceException(ResultCode.FAIL_TO_UPLOAD);
        }
        return url;
    }

    /**
     * 手机号登录
     *
     * @param phone
     * @param code
     * @return
     */
    @Override
    public Serializable login(String phone, String code) {
        String o = (String) valueOperations.get(MsgServiceImpl.PREFIX_REDIS_KEY + phone);
        if (ObjectUtils.isEmpty(o)) {
            throw new ServiceException(ResultCode.AUTH_ERROR);
        }
        if (!o.equals(code)) {
            throw new ServiceException(ResultCode.IDEM_TOKEN_ERROR);
        }
        valueOperations.set(MsgServiceImpl.PREFIX_REDIS_KEY + phone, code, Duration.ofSeconds(1));
        UsernamePasswordToken token = new UsernamePasswordToken(phone, code);
        try {
            SecurityUtils.getSubject().login(token);
        } catch (UnknownAccountException | IncorrectCredentialsException e) {
            throw new ControllerException(ResultCode.IDEM_TOKEN_ERROR);
        } catch (LockedAccountException e) {
            throw new ControllerException(ResultCode.UN_LOGIN);
        } catch (Exception e) {
            throw new ControllerException(ResultCode.AUTH_ERROR);
        }
        //获取jSessionId
        Serializable id = ShiroUtils.getSession().getId();
        return id;
    }

}

